package com.niuniu;

import com.xingli.zhajinhua.beans.Card;
import com.xingli.zhajinhua.beans.PlayerCards;
import com.xingli.zhajinhua.beans.niuniu.enums.NiuCardColor;
import com.xingli.zhajinhua.beans.niuniu.enums.NiuCardPoint;
import com.xingli.zhajinhua.beans.niuniu.enums.NiuCardType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class NiuNiuLogic extends AbstractCardsGame {

    public NiuNiuLogic() {
        super(2, 5, 64);
    }

    public NiuNiuLogic(int playerNumber, int playerCardNumber, int baseWeight) {
        super(playerNumber, playerCardNumber, baseWeight);
    }


//生成所有的牌并洗牌
    @Override
    public List<Card> getNewCardCollectionAndShuffle() {
        NiuCardColor[] cardColors = NiuCardColor.values();
        NiuCardPoint[] cardPoints = NiuCardPoint.values();
        List<Card> cardList = new ArrayList<>(cardColors.length * cardPoints.length);
        for (NiuCardColor color : cardColors) {
            for (NiuCardPoint points : cardPoints) {
                int weight = ((points.weight - 1) * (cardColors.length) + color.weight);
                cardList.add(new Card(points.ordinal(), color.ordinal(), points.weight, color.weight, weight));
            }
        }
        Collections.shuffle(cardList);
        return cardList;
    }

    @Override
    public String judgeCardType(Card[] card) {
        if (isFiveSmall(card)) {
            return NiuCardType.FiveSmall.name();
        }
        if (isBoom(card)) {
            return NiuCardType.Boom.name();
        }
        if (isHuLu(card)) {
            return NiuCardType.HuLu.name();
        }
        if (isTongHua(card)) {
            return NiuCardType.TongHua.name();
        }
        if (isShunZi(card)) {
            return NiuCardType.ShunZi.name();
        }
        if (isWuHua(card)) {
            return NiuCardType.WuHua.name();
        }
        return getNiuNumber(card).name();
    }

    @Override
    public int calculateCardsWeight(Card[] cards, String cardType) {
        int weight;
        NiuCardType type = NiuCardType.valueOf(cardType);
        switch (type) {
            case Boom:
            case HuLu:
                if (cards[0].getPointWeight() == cards[2].getPointWeight()) {
                    weight = (int) (type.weight * Math.pow(baseWeight, 2)
                            + cards[2].getPointWeight()) * baseWeight
                            + cards[0].getWeight();
                } else {
                    weight = (int) (type.weight * Math.pow(baseWeight, 2)
                            + cards[2].getPointWeight()) * baseWeight
                            + cards[4].getWeight();
                }
                break;
            case FiveSmall:
            case TongHua:
            case ShunZi:
            case WuHua:
                weight = (int) (type.weight * Math.pow(baseWeight, 2) + cards[4].getWeight());
                break;
            case NoNiu:
                weight = cards[4].getWeight();
                break;
            default:
                //有牛的情况下
                int lastTwoCardWeight = 0;
                int totalNum = 0;
                for (Card niuCard : cards) {
                    if (niuCard.getPointWeight() > 10) {
                        totalNum += 10;
                    } else {
                        totalNum += niuCard.getPointWeight();
                    }
                }
                for (int i = 0; i < cards.length - 1; i++) {
                    for (int j = i + 1; j < cards.length; j++) {
                        int twoCardValue = cards[i].getPointWeight() > 10 ? 10 : cards[i].getPointWeight() +
                                cards[j].getPointWeight() > 10 ? 10 : cards[j].getPointWeight();
                        //是牛
                        if ((totalNum - twoCardValue) % 10 == 0) {
                            //取剩下牌中最大的牌的权重
                            if (cards[i].getWeight() > lastTwoCardWeight) {
                                lastTwoCardWeight = cards[i].getWeight();
                            }
                            if (cards[j].getWeight() > lastTwoCardWeight) {
                                lastTwoCardWeight = cards[j].getWeight();
                            }
                        }

                    }
                }
                weight = (int) (type.weight * Math.pow(baseWeight, 2) + lastTwoCardWeight);
                break;
        }

        return weight;
    }


    //判断是否是五小
    public boolean isFiveSmall(Card[] card) {
        int cardNumber = 0; //牌数
        int cardValue = 0; //牌的总点数
        for (Card aCard : card) {
            if (5 > aCard.getPointWeight()) {
                cardNumber++;
            }
            cardValue += aCard.getPointWeight();
        }
        return cardNumber == 5 && cardValue <= 10;
    }

    //判断是否是炸弹
    public boolean isBoom(Card[] card) {
        if (card[0].getPointWeight() == card[1].getPointWeight() &&
                card[0].getPointWeight() == card[2].getPointWeight() &&
                card[0].getPointWeight() == card[3].getPointWeight()
                ) {
            return true;
        }

        if (card[1].getPointWeight() == card[2].getPointWeight() &&
                card[2].getPointWeight() == card[3].getPointWeight() &&
                card[3].getPointWeight() == card[4].getPointWeight()) {
            return true;
        }
        return false;
    }

    //判断是否是葫芦
    public boolean isHuLu(Card[] card) {
        if (card[0].getPointWeight() == card[1].getPointWeight() &&
                card[0].getPointWeight() == card[2].getPointWeight()
                &&card[3].getPointWeight() == card[4].getPointWeight()) {
            return true;
        }

        if (card[1].getPointWeight() == card[2].getPointWeight() &&
                card[2].getPointWeight() == card[3].getPointWeight()
                &&card[0].getPointWeight() == card[4].getPointWeight()) {
            return true;
        }
        if (card[2].getPointWeight() == card[3].getPointWeight() &&
                card[2].getPointWeight() == card[4].getPointWeight()
                &&card[1].getPointWeight() == card[0].getPointWeight()) {
            return true;
        }
        return false;
    }

    //判断是否是同花
    public boolean isTongHua(Card[] card) {
        return (card[0].getColorWeight() == card[1].getColorWeight() &&
                card[0].getColorWeight() == card[2].getColorWeight() &&
                card[0].getColorWeight() == card[3].getColorWeight() &&
                card[0].getColorWeight() == card[4].getColorWeight());
    }

    //判断是否是顺子
    public boolean isShunZi(Card[] card) {
        return (card[0].getPointWeight() + 1 == card[1].getPointWeight() &&
                card[1].getPointWeight() + 1 == card[2].getPointWeight() &&
                card[2].getPointWeight() + 1 == card[3].getPointWeight() &&
                card[3].getPointWeight() + 1 == card[4].getPointWeight()
        );
    }

    //判断是否是5花
    public boolean isWuHua(Card[] cards) {
        int count = 0;
        for (Card card : cards) {
            if (card.getPointWeight() > NiuCardPoint.Number10.weight) {
                count++;
            }
        }
        return (count == playerCardNumber);
    }

    //判断是牛几
    public NiuCardType getNiuNumber(Card[] niuCards) {
        //5个中选三个  C53 = C52 最多的不重复组合是10
        NiuCardType niuCardType = NiuCardType.NoNiu;
        int totalNum = 0;
        for (Card card : niuCards) {
            if (card.getPointWeight() > 10) {
                totalNum += 10;
            } else {
                totalNum += card.getPointWeight();
            }
        }
        for (int i = 0; i < niuCards.length - 1; i++) {
            for (int j = i + 1; j < niuCards.length; j++) {
                int twoCardValue = (niuCards[i].getPointWeight() > 10 ? 10 : niuCards[i].getPointWeight()) +
                        (niuCards[j].getPointWeight() > 10 ? 10 : niuCards[j].getPointWeight());
                //计算剩余3张牌的价值 看是否有牛
                if ((totalNum - twoCardValue) % 10 == 0) {
                    //计算他是牛几
                    String niuNumber = "Niu" + twoCardValue % 10;
                    niuCardType = NiuCardType.valueOf(niuNumber);
                    break;
                }

            }
        }
        return niuCardType;
    }
}
